package com.comunity_cloud.client.model.file_list;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import com.comunity_cloud.client.model.CommunityFile;
import com.comunity_cloud.client.model.Configuration;
import com.comunity_cloud.client.model.MainModel2;
import com.comunity_cloud.client.model.communication.ConnectionsManager;
import com.comunity_cloud.client.model.communication.PacketListener;
import com.comunity_cloud.client.model.communication.PeerConnection;
import com.comunity_cloud.client.model.communication.packet.PeerPacket;
import com.comunity_cloud.client.model.communication.packet.PeerPacketHeader.Type;
import com.comunity_cloud.client.model.file_list.SendMeFilesResponse.FileInfo;
import com.comunity_cloud.client.model.upload_file.FileChunkHeader;
import com.user_hosted_storage.dto.CommunityDTO;
import com.user_hosted_storage.dto.CommunityMemberDTO;

public class FileListClient extends Thread implements PacketListener<SendMeFilesResponse>{

	private static final long INTERVAL = 5000;
	private Map<Long,Vector<CommunityFilesListener>> listeners = new Hashtable<>(); 
	
	public FileListClient() {
		PeerConnection.addPacketListener(Type.SEND_ME_FILES_RESPONSE, this);
		start();
	}
	
	@Override
	public void run() {
		SendMeFilesHeader sendMeFilesHeader = new SendMeFilesHeader();
		PeerPacket<SendMeFilesHeader> peerPacket = new PeerPacket<>(sendMeFilesHeader,null);
		
		while(true) {
			Collection<CommunityDTO> communities = MainModel2.getInstance().getCommunities();
			
			byte[] chunkHeaderBytes = new byte[FileChunkHeader.SIZE];
			FileChunkHeader fileChunkHeader = new FileChunkHeader();
			
			for (CommunityDTO community : communities) {
				File communityHostedDir = new File(Configuration.getInstance().hostedFilesPath + community.getName());
				Vector<CommunityFilesListener> communityListeners = listeners.get(community.getId());
				communityHostedDir.mkdirs();
				File[] files = communityHostedDir.listFiles();

				for (File file : files) {
					try {
						if (file.getName().equals(".tmp")) {
							continue;
						}
						FileInputStream in = new FileInputStream(file);
						in.read(chunkHeaderBytes);

						in.close();

						fileChunkHeader.fromBytes(chunkHeaderBytes);

						CommunityFile communityFile = new CommunityFile(community);
						
						communityFile.updateChunk(fileChunkHeader.getTotalOffset(),fileChunkHeader.isPrimary(),MainModel2.getInstance().getCommunityMember(community.getId(), MainModel2.getInstance().getClientDTO().getId()), file.length());
						
						communityFile.setLength(fileChunkHeader.getTotalSize());
						communityFile.setPath(file.getName().replaceFirst(""+fileChunkHeader.getTotalOffset(), ""));
						communityFile.setState(CommunityFile.State.SYNCHRONIZED);
						
						if (communityListeners != null) {
							for (CommunityFilesListener communityFilesListener : communityListeners) {
								communityFilesListener.newCommunityFileAdded(communityFile);
							}
						}
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					} catch (IOException e) {
						e.printStackTrace();
					}

				}
			}
			
			for (CommunityDTO communityDTO : communities) {
				List<CommunityMemberDTO> members = MainModel2.getInstance().getOnlineHosts(communityDTO);
				for (CommunityMemberDTO communityMemberDTO : members) {
					
					try {
						PeerConnection peerConnection = ConnectionsManager.getInstance().getPeerConnection(communityMemberDTO.getClient().getId());
						
						if(peerConnection == null) {
							continue;
						}
						sendMeFilesHeader.setCommunityId(communityDTO.getId());
						peerConnection.sendPacket(peerPacket);						
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			
			
			
			try {
				Thread.sleep(INTERVAL);
			} catch (InterruptedException e) {}
		}
	}
	
	@Override
	public void packetReceived(PeerPacket<SendMeFilesResponse> peerPacket) {
		
		SendMeFilesResponse header = peerPacket.getHeader();
		
		long communityId = header.getCommunityId();
		
		CommunityDTO community = MainModel2.getInstance().getCommunity(communityId);
		
		Vector<CommunityFilesListener> communityListeners = listeners.get(communityId);
		if(communityListeners != null) {
			List<FileInfo> files = header.getFiles();
			for (FileInfo fileInfo : files) {
				CommunityFile communityFile = new CommunityFile(community);
				communityFile.setPath(fileInfo.fileName);
				communityFile.setImage(fileInfo.image);
				communityFile.setLength(fileInfo.fileSize);
				communityFile.setState(CommunityFile.State.SYNCHRONIZED);
				communityFile.updateChunk(fileInfo.totalOffset, fileInfo.isPrimary, MainModel2.getInstance().getCommunityMember(communityId, peerPacket.getClientId()), fileInfo.chunkSize);
				for (CommunityFilesListener communityFilesListener : communityListeners) {
					communityFilesListener.newCommunityFileAdded(communityFile);
				}
			}
		}		
		
	}
	
	public void addCommunityFilesListener(long communityId, CommunityFilesListener listener) {
		Vector<CommunityFilesListener> communityListeners = listeners.get(communityId);
		if(communityListeners == null) {
			communityListeners = new Vector<>();
			listeners.put(communityId, communityListeners);
		}
		if(!communityListeners.contains(listener)) {
			communityListeners.add(listener);
		}
	}
	
	public void removeCommunityListener(long communityId, CommunityFilesListener listener){
		Vector<CommunityFilesListener> communityListeners = listeners.get(communityId);
		if(communityListeners == null) {
			return;
		}
		communityListeners.remove(listener);
	}
}
